package hu.veilingsite.gui;

import hu.veilingsite.shared.Auction;
import hu.veilingsite.shared.Bid;
import hu.veilingsite.shared.Category;
import hu.veilingsite.shared.FieldVerifier;
import hu.veilingsite.client.Service;
import hu.veilingsite.client.ServiceAsync;
import hu.veilingsite.client.Systeem;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;

public class ViewAuction {
	private int auctionID;
	private Button BTN_offer, BTN_terug, BTN_wijzig, BTN_verwijder;
	private TextBox TB_offer;
	private ArrayList<Category> categories;
	private ArrayList<Bid> biedingen;
	private final FlexTable biedingPanel = new FlexTable();
	private final ServiceAsync myService = GWT.create(Service.class);

	public ViewAuction(final int id) {
		auctionID = id;
		categories = new ArrayList<Category>();

		//void callback om veilingen te verwijderen
		final AsyncCallback<Void> sterf = new AsyncCallback<Void>(){

			@Override
			public void onFailure(Throwable caught) {
				FieldVerifier.showMessageBox("Oops", "Er is iets fout gegaan op de server..", true);
			}
			@Override
			public void onSuccess(Void result) {
				FieldVerifier.showMessageBox("goed nieuws", "De veiling is verwijderd", true);
			}
		};

		// get categories
		AsyncCallback<ArrayList<Category>> getCategoriesCallback = new AsyncCallback<ArrayList<Category>>(){
			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				RootPanel.get("main").clear();
				RootPanel.get("main").add(new ShowAuctions().createPage());
			}

			@Override
			public void onSuccess(ArrayList<Category> result) {
				categories = result;
				myService.getBidsFromAuction(auctionID,new AsyncCallback<ArrayList<Bid>>() {
					public void onFailure(Throwable caught) {
						caught.printStackTrace();
						FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan met het ophalen van de biedingen, probeer het opnieuw.", true);
					}
					public void onSuccess(ArrayList<Bid> result) {
						biedingen = result;
						// onsucces get Auction
						AsyncCallback<Auction> getAuction = new AsyncCallback<Auction>(){
							@Override
							public void onFailure(Throwable caught) {
								caught.printStackTrace();
								RootPanel.get("main").clear();
								RootPanel.get("main").add(new ShowAuctions().createPage());
							}
							@Override
							public void onSuccess(final Auction auction) {
								if (auction.isVisible()) {
									FlexTable table = new FlexTable();
									table.addStyleName("nicetable");
									// search category name by id
									String catName = "";
									for(int i = 0; i < categories.size(); i++) {
										Category cat = categories.get(i);
										if (cat.getId() == auction.getCategory_id()) {
											catName = cat.getTitle();
											i = categories.size();
										}
									}
									String tijdover = tijdover(auction.getEndDate());
									// add widgets to flextable
									table.setWidget(0, 0, new HTML("<h1>" + catName + " > " + auction.getTitle() + "</h1>"));
									table.setWidget(1, 0, new Label("Omschrijving: "));
									table.setWidget(1, 1, new Label(auction.getDescription()));
									table.setWidget(2, 0, new Label("Loopt tot: "));
									table.setWidget(2, 1, new Label("" + auction.getEndDate()));
									table.setWidget(3, 0, new Label("Tijd over: "));
									table.setWidget(3, 1, new Label(tijdover));
									table.setWidget(4, 0, new Label("Beginprijs: "));
									table.setWidget(4, 1, new Label("" + auction.getStartprice() + " credits"));
									// add biedingPanel
									biedingPanel.setWidget(0, 0, new Label("Alle biedingen:"));
									if (biedingen.size() > 0) {
										biedingPanel.setWidget(1, 0, new Label("Geboden door:"));
										biedingPanel.setWidget(1, 1, new Label("Met credits:"));
										biedingPanel.setWidget(1, 2, new Label("Op datum:"));
										for (int i = 0; i < biedingen.size(); i++) {
											final Bid bid = biedingen.get(i);
											int row = i+2;
											getNameOfUser(row, bid.getUser_id());
											biedingPanel.setWidget(row, 1, new Label("" + bid.getCredits()));
											biedingPanel.setWidget(row, 2, new Label("" + bid.getDate()));
											if(!(Systeem.ingelogd == null) && Systeem.ingelogd.getId() == bid.getUser_id()){
												ClickHandler annuleerHandler = new ClickHandler() {
													@Override
													public void onClick(ClickEvent event) {
														annuleerBieding(bid.getId());
													}
												};
												biedingPanel.setWidget(row, 3, new Button("annuleer",annuleerHandler));
											} else if (!(Systeem.ingelogd == null) && Systeem.ingelogd.getId() == auction.getAuthor_id()) {
												ClickHandler acceptHandler = new ClickHandler() {
													@Override
													public void onClick(ClickEvent event) {
														acceptBieding(bid.getId());
													}
												};
												biedingPanel.setWidget(row, 3, new Button("accepteer",acceptHandler));
											}
										}
									} else {
										biedingPanel.setWidget(1, 0, new Label("Er zijn nog geen biedingen gedaan."));
									}

									if (Systeem.ingelogd != null && Systeem.ingelogd.getId() != auction.getAuthor_id() && !tijdover.equals("Veiling gesloten.") && Systeem.ingelogd.isMaybid()) {
										TB_offer = new TextBox();
										table.setWidget(5, 0, TB_offer);

										BTN_offer = new Button("Bied");
										BTN_offer.addClickHandler(new ClickHandler() {
											public void onClick(ClickEvent e) {
												int offer = -1;
												try {
													offer = Integer.parseInt(TB_offer.getText());
												} catch(Exception exc) {
													FieldVerifier.showMessageBox("Oops!", "vul alleen getallen in!.", true);
												}
												if (offer > 0 && Systeem.ingelogd.getCredits()-offer >= 0) {
													createBieding(offer);
												} else {
													FieldVerifier.showMessageBox("Oops!", "U heeft niet voldoende credits.", true);
												}
											}
										});
										table.setWidget(5, 1, BTN_offer);
										
									} else if(tijdover.equals("Veiling gesloten.")) {
										table.setWidget(5, 0, new Label("Deze veiling is gesloten, er kan niet meer gebied worden."));
									} else if (Systeem.ingelogd != null  && Systeem.ingelogd.getId() == auction.getAuthor_id()) {
										table.setWidget(5, 0, new Label("U kunt niet bieden op uw eigen veilingen."));
									} else if (Systeem.ingelogd != null  && !Systeem.ingelogd.isMaybid()) {
										table.setWidget(5, 0, new Label("U heeft geen rechten om te bieden op veilingen."));
									} else {
										table.setWidget(5, 0, new Label("log eerst in om te kunnen bieden."));
									}
									// add wijzig button en verwijder button
									if(!(Systeem.ingelogd == null) && (Systeem.ingelogd.isIsadmin() || Systeem.ingelogd.getId() == auction.getAuthor_id())){
										BTN_wijzig = new Button("Wijzig");
										BTN_wijzig.addClickHandler(new ClickHandler() {
											public void onClick(ClickEvent e) {
												new EditAuction().createPage(auction.getId());
											}
										});
										table.setWidget(7, 1, BTN_wijzig);

										BTN_verwijder = new Button("verwijder de veiling");
										BTN_verwijder.addClickHandler(new ClickHandler() {
											public void onClick(ClickEvent e) {
												RootPanel.get("main").clear();
												RootPanel.get("main").add(new ShowAuctions().createPage());
												myService.deleteAuction(auction.getId(), sterf);
											}
										});
										table.setWidget(7, 2, BTN_verwijder);
									}
									// add terug button
									BTN_terug = new Button("Terug");
									BTN_terug.addClickHandler(new ClickHandler() {
										public void onClick(ClickEvent e) {
											RootPanel.get("main").clear();
											RootPanel.get("main").add(new ShowAuctions().createPage());
										}
									});
									table.setWidget(7, 0, BTN_terug);

									RootPanel.get("main").add(table);
									RootPanel.get("main").add(biedingPanel);
								} else {
									RootPanel.get("main").clear();
									RootPanel.get("main").add(new ShowAuctions().createPage());
								}
							}
						};
						myService.getAuction(id, getAuction);
					}

					public void annuleerBieding(int bidId){
						AsyncCallback<Boolean> deleteBid = new AsyncCallback<Boolean>(){
							@Override
							public void onFailure(Throwable caught) {
								RootPanel.get("main").clear();
								RootPanel.get("main").add(new HTML("Er is een fout opgetreden in het systeem."));
							}

							@Override
							public void onSuccess(Boolean result) {
								if (result) {
									FieldVerifier.showMessageBox("Geannuleert", "Uw bieding is succesvol geannuleerd.", true);
									RootPanel.get("main").clear();
									RootPanel.get("main").add(new ViewAuction(auctionID).createPage());
								} else {
									FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan, probeer het opnieuw.", true);
								}
							}
						};
						myService.deleteBid(bidId, deleteBid);
					}

					public void acceptBieding(int bidId){
						AsyncCallback<Boolean> acceptBid = new AsyncCallback<Boolean>(){
							@Override
							public void onFailure(Throwable caught) {
								FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan, probeer het opnieuw.\n" + caught.getMessage(), true);
							}

							@Override
							public void onSuccess(Boolean result) {
								if (result) {
									FieldVerifier.showMessageBox("Geaccepteerd", "De bieding is geaccepteerd.\nUw Veiling is verwijderd en de credits zijn overgemaakt.", true);
									RootPanel.get("main").clear();
									RootPanel.get("main").add(new ProfileAuctions().createPage());
								} else {
									FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan, probeer het opnieuw.", true);
								}
							}
						};
						myService.acceptBid(bidId, acceptBid);
					}

					public void getNameOfUser(final int row, int userId) {
						AsyncCallback<String> getNameOfUser = new AsyncCallback<String>(){
							@Override
							public void onFailure(Throwable caught) {
								RootPanel.get("main").clear();
								RootPanel.get("main").add(new HTML("Er is een fout opgetreden in het systeem."));
							}

							@Override
							public void onSuccess(String name) {
								biedingPanel.setWidget(row, 0, new Label(name));
							}
						};
						myService.getNameOfUser(userId, getNameOfUser);

					}
				});
			}
		};
		myService.getCategories(getCategoriesCallback);
	}

	public Panel createPage() {
		return new HorizontalPanel();
	}

	public void createBieding(int offer) {
		myService.createBieding(Systeem.ingelogd.getId(), auctionID, offer, new Date(), new AsyncCallback<Boolean>() {
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan, probeer het opnieuw.", true);
			}
			public void onSuccess(Boolean gelukt) {
				if (gelukt) {
					FieldVerifier.showMessageBox("Gelukt!", "U heeft succesvol een bieding gedaan.", true);
					RootPanel.get("main").clear();
					RootPanel.get("main").add(new ViewAuction(auctionID).createPage());
				} else {
					FieldVerifier.showMessageBox("Oops!", "Er is iets fout gegaan, probeer het opnieuw.", true);
				}
			}
		});
	}

	public String tijdover(Date einddatum) {
		Date until = new Date(einddatum.getTime());
		Date now = new Date();
		String tijdover = "";
		long timeleft = until.getTime() - now.getTime();
		if(timeleft > 0){
			// Easy as that ;D
			long days = (long) Math.ceil(timeleft / (1000 * 60 * 60 * 24));
			timeleft = timeleft - (days * (1000 * 60 * 60 * 24));
			if(days > 0) tijdover += days + " dagen ";
			long hours = (long) Math.ceil(timeleft / (1000 * 60 * 60));
			timeleft = timeleft - (hours * (1000 * 60 * 60));
			if(hours > 0) tijdover += hours + " uur ";
			long min = (long) Math.ceil(timeleft / (1000 * 60));
			timeleft = timeleft - (min * (1000 * 60));
			if(min > 0) tijdover += min + " min ";
			long sec = (long) Math.ceil(timeleft / (1000));
			timeleft = timeleft - (sec * (1000));
			tijdover += sec + " sec.";
		}
		else{
			tijdover = "Veiling gesloten.";
		}
		return tijdover;
	}
}
